using System;
using System.Collections.Generic;
using System.Linq;

namespace octalforty.Componento.Core.ApplicationServices
{
    public class DependencyGraph
    {
        private readonly List<DependencyGraphNode> nodes = new List<DependencyGraphNode>();

        public IEnumerable<DependencyGraphNode> Nodes
        {
            get { return nodes; }
        }

        public DependencyGraphNode GetNodeFor(string name, Version version)
        {
            return nodes.FirstOrDefault(n => string.Compare(n.Manifest.Name, name, true) == 0 && n.Manifest.Version == version);
        }

        public void AddNode(DependencyGraphNode node)
        {
            nodes.Add(node);
        }
    }

    public class DependencyGraphVisitor
    {
        private readonly IList<DependencyGraphNode> visitedNodes = new List<DependencyGraphNode>();
        private readonly DependencyGraphVisitorCallback action;

        public DependencyGraphVisitor(DependencyGraphVisitorCallback action)
        {
            this.action = action;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="node"></param>
        public void Visit(DependencyGraphNode node)
        {
            VisitRecursive(node, 0);
        }

        private void VisitRecursive(DependencyGraphNode node, int depth)
        {
            if(visitedNodes.Contains(node)) return;

            visitedNodes.Add(node);
            action(depth, node);

            foreach(var childNode in node.DependentOn)
                VisitRecursive(childNode, depth + 1);
        }
    }

    public class DependencyGraphInspector
    {}

    public delegate void DependencyGraphVisitorCallback(int depth, DependencyGraphNode node);
}